package com.ikingtech.platform.service.oidc.endpoint.token;

import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.oidc.client.service.OidcClientRedirectUriRepository;
import com.ikingtech.platform.service.oidc.client.service.OidcClientRepository;
import com.ikingtech.platform.service.oidc.exception.ServerErrorException;
import com.ikingtech.platform.service.oidc.exception.UnauthorizedClientException;
import com.ikingtech.platform.service.oidc.web.OidcAuthorizationRequest;
import com.ikingtech.platform.service.oidc.web.OidcAuthorizationResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.MultiValueMap;

/**
 * @author tie yan
 */
public class OidcAuthorizationCodeTokenRequestEndpoint extends AbstractOidcTokenEndpoint {

    private final StringRedisTemplate redisTemplate;

    public OidcAuthorizationCodeTokenRequestEndpoint(OidcClientRepository clientRepo,
                                                     OidcClientRedirectUriRepository clientRedirectUriRepo,
                                                     StringRedisTemplate redisTemplate) {
        super(clientRepo, clientRedirectUriRepo);
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected OidcAuthorizationResponse doAuthorization(OidcAuthorizationRequest authorizationRequest) {
        OidcAuthorizationResponse authorizationResponse = new OidcAuthorizationResponse();
        String authorizationCodeRequestStr = this.redisTemplate.opsForValue().get(Tools.Str.format("oidc:authorization_code:{}:{}", authorizationRequest.getClientId(), authorizationRequest.getCode()));
        if (Tools.Str.isBlank(authorizationCodeRequestStr)) {
            throw new UnauthorizedClientException();
        }
        OidcAuthorizationRequest authorizationCodeRequest = Tools.Json.toBean(authorizationCodeRequestStr, OidcAuthorizationRequest.class);
        if (null == authorizationCodeRequest) {
            throw new ServerErrorException();
        }
        if (Tools.Str.isNotBlank(authorizationCodeRequestStr)) {
            if (Tools.Str.isNotBlank(authorizationCodeRequest.getRedirectUri())) {

            }
            authorizationResponse.setAccessToken(Tools.Id.uuid());
            authorizationResponse.setTokenType("Bearer");
            authorizationResponse.setExpiresIn(3600L);
            authorizationResponse.setRefreshToken(Tools.Id.uuid());
            this.redisTemplate.delete(Tools.Str.format("oidc:authorization_code:{}:{}", authorizationRequest.getClientId(), authorizationRequest.getCode()));
            return authorizationResponse;
        } else {
            throw new UnauthorizedClientException();
        }
    }

    @Override
    public OidcAuthorizationRequest convertRequest(MultiValueMap<String, String> paramMap) {
        OidcAuthorizationRequest authorizationRequest = super.convertRequest(paramMap);
        String code = paramMap.getFirst(OidcAuthorizationRequest.AuthenticationRequestFieldName.CODE);
        if (Tools.Str.isBlank(code)) {
            throw new UnauthorizedClientException();
        }
        authorizationRequest.setCode(code);
        return authorizationRequest;
    }

    @Override
    public boolean support(String grantType) {
        return "authorization_code".equals(grantType);
    }
}
